package com.system.es;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.system.common.Result;
import com.system.util.ReflectUtils;
import io.searchbox.client.http.JestHttpClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.omg.PortableServer.LIFESPAN_POLICY_ID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;


import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Classname EsServer
 * @Description TODO
 * @Date 2023/2/28 11:35
 * @Created by XiongXiong
 * @Author: X.I.O
 */
@Component
public class EsServer {

    private final static String ID="id";

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    @Autowired
    @Qualifier("getRestClient")
    private RestClient restClient;

    public RestClient getClient(){
        return restClient;
    }

    public RestHighLevelClient getRestHighLevelClient(){
        return client;
    }

    /**
     * 创建索引
     * @param indexName
     * @throws IOException
     */
    public  void createIndex(String indexName) throws IOException {
        //1. 创建索引
        CreateIndexRequest index = new CreateIndexRequest(indexName);
        //2. 客户端执行请求,请求后获得相应
        CreateIndexResponse response = client.indices().create(index, RequestOptions.DEFAULT);
        //3.打印结果
        System.out.println(response.toString()+"这是结果");
    }

    /**
     * 获取索引
     * @return 获取所有索引
     * @throws IOException
     */
    public List<String> getAllIndexs() throws IOException {
        GetAliasesRequest request = new GetAliasesRequest();
        GetAliasesResponse getAliasesResponse =  client.indices().getAlias(request,RequestOptions.DEFAULT);
        Map<String, Set<AliasMetaData>> map = getAliasesResponse.getAliases();
        Set<String> indices = map.keySet();
        List<String> strings=new ArrayList<>();
        for (String key : indices) {
            strings.add(key);
        }
        return strings;
    }


    /**
     * 判断索引是否存在
     * @param indexName
     * @return
     * @throws IOException
     */
    public boolean exitIndex(String indexName) throws IOException{
        GetIndexRequest request = new GetIndexRequest(indexName);
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        return exists;
    }

    /**
     * 通过索引的id获取单个数据对象
     * @param indexName 索引
     * @param idValue  id值
     * @param cls    反射类
     * @param <T>   反射泛型
     * @return  单个数对象
     * @throws IOException
     */
    public <T> T getDocumentById(String indexName,String idValue,Class<T> cls) throws IOException {
        GetRequest request = new GetRequest(indexName, idValue);
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        Map<String, Object> map=response.getSource();
        T t =MapUtils.getObject(map,cls);
        return t;
    }


    public Map<String,Object> getDocumentById(String indexName,String idValue) throws IOException {
        GetRequest request = new GetRequest(indexName, idValue);
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        Map<String, Object> map=response.getSource();
        return map;
    }

    public List<Map<String,Object>> getAllDocuments(String indexName) throws IOException {
        SearchRequest request = new SearchRequest(indexName);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        request.source(sourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        List<Map<String,Object>> maps = new ArrayList<Map<String, Object>>();
        for (SearchHit hit : hits) {
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("id",hit.getId());
            map.put("indexName",hit.getIndex());
            map.put("data",hit.getSourceAsMap());
            maps.add(map);
        }
        return maps;
    }

    public Map<String,Object> pageSearch(String indexName,Integer pageNum,Integer pageSize) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 查询所有文档
        searchSourceBuilder.from((pageNum - 1) * pageSize); // 起始位置
        searchSourceBuilder.size(pageSize); // 分页大小
        searchSourceBuilder.timeout(new TimeValue(60L, TimeUnit.SECONDS)); // 设置超时时间
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<Map<String,Object>> maps = new ArrayList<Map<String, Object>>();
        for (SearchHit hit : hits) {
            System.out.println("高亮信息：" + hit.getHighlightFields());
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("id",hit.getId());
            map.put("indexName",hit.getIndex());
            map.put("data",hit.getSourceAsMap());
            maps.add(map);
        }
        Long total=searchResponse.getHits().getTotalHits().value;
        Map<String, Object> data=new HashMap<String, Object>();
        data.put("list",maps);
        data.put("total",total);
        return data;
    }

    public JSONObject addDocumentFiled(String indexName,Map<String,Object> documentField) throws IOException {
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        for (Map.Entry<String, Object> entry : documentField.entrySet()) {
            builder.field(entry.getKey(), entry.getValue());
        }
        builder.endObject();
        IndexRequest indexRequest = new IndexRequest(indexName).id(UUID.randomUUID().toString()).source(builder);
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
        return Result.successInfo("添加成功");
    }


    /**
     *
     * @param indexName  索引名字
     * @param field      字段
     * @param search     搜索内容
     * @param pageNum     页码
     * @param pageSize   大小
     * @return
     */
    public Map<String,Object> pageHightLightFuzzSearch(String indexName,String field,String search,Integer pageNum,Integer pageSize) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //分词查询字段
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(field, search)
                .fuzziness(Fuzziness.AUTO);


        searchSourceBuilder.query(matchQueryBuilder);
        searchSourceBuilder.from((pageNum - 1) * pageSize); // 起始位置
        searchSourceBuilder.size(pageSize); // 分页大小
        searchSourceBuilder.timeout(new TimeValue(60L, TimeUnit.SECONDS)); // 设置超时时间

        //指定需要返回或者排除的字段
        String[] includes = {field};
        String[] excludes = {};
    //    searchSourceBuilder.fetchSource(includes, excludes);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
      //  highlightBuilder.requireFieldMatch(true); // 不匹配需要高亮的字段也会被高亮
        highlightBuilder.field(field); // 高亮字段
        highlightBuilder.preTags("<span style='color:red'>"); // 高亮标签
        highlightBuilder.postTags("</span>");

        searchRequest.source(searchSourceBuilder);
        searchRequest.source().highlighter(highlightBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();


        List<Map<String,Object>> maps = new ArrayList<Map<String, Object>>();

        for (SearchHit hit : hits) {
            System.out.println("高亮信息：" + hit.getHighlightFields());
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("id",hit.getId());
            map.put("indexName",hit.getIndex());
            map.put("data",hit.getSourceAsMap());
            map.put("type",hit.getType());
            System.out.println(JSONObject.toJSON(hit.getFields()));
            System.out.println(JSONObject.toJSON(hit.getSourceAsString()));
            //获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            System.out.println(JSONObject.toJSON(highlightFields));
            StringBuilder stringBuilder=new StringBuilder();
            //如果高亮字段包含在description中
            if (highlightFields.containsKey(field)){
                Text[] fragments = highlightFields.get(field).getFragments();
                for (Text fragment : fragments) {
                   stringBuilder.append(fragment);
                }
            }
            map.put("highlight",stringBuilder.toString());
            maps.add(map);
        }

        Long total=searchResponse.getHits().getTotalHits().value;
        Map<String, Object> data=new HashMap<String, Object>();
        data.put("list",maps);
        data.put("total",total);
        return data;
    }

    public Map<String,Object> highLights(String indexName,String search) throws IOException {
        //1.创建 SearchRequest搜索请求,并指定要查询的索引
        SearchRequest searchRequest = new SearchRequest(indexName);

        //2.创建 SearchSourceBuilder条件构造。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();


        searchSourceBuilder.query(QueryBuilders.functionScoreQuery(QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("title", search).boost(3.0f))  // 设置权重大的字段
                .should(QueryBuilders.matchQuery("tag", search).boost(2.3f))  // 设置权重略低的字段
                .should(QueryBuilders.matchQuery("channelName", search).boost(2.2f))
                .should(QueryBuilders.matchQuery("content", search).boost(2.0f))
                .minimumShouldMatch(1)  // 指定至少有一个should子句匹配
        ).boostMode(CombineFunction.SUM)  // 设置权重计算模式为加和
         .setMinScore(2.0f));  // 设置最小分数阈值，低于此阈值的结果会受到影响

        // 构造排序规则
       // SortBuilder scoreSort = SortBuilders.scoreSort().order(SortOrder.DESC)("_last");
        SortBuilder creationDateSort = SortBuilders.fieldSort("createDate").order(SortOrder.DESC);

        // 将排序规则添加到查询中
      //  searchSourceBuilder.sort(scoreSort);
        searchSourceBuilder.sort(creationDateSort);

//        //分词查询字段
//        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//
//       // boolQuery.should(QueryBuilders.matchQuery("title", search).fuzziness(Fuzziness.AUTO).boost(5.0f).analyzer("ik_smart"));
//
//        //boolQuery.should(QueryBuilders.matchPhraseQuery("title", search).boost(4.0f).analyzer("ik_smart"));
//       // boolQuery.should(QueryBuilders.matchPhraseQuery("tag",search).boost(3.2f).analyzer("ik_smart"));
//        //boolQuery.should(QueryBuilders.matchPhraseQuery("content", search).boost(1.0f).analyzer("ik_smart"));
//       // boolQuery.should(QueryBuilders.matchPhraseQuery("channelName", search).boost(2.0f).analyzer("ik_smart"));
//
//        boolQuery.should(QueryBuilders.functionScoreQuery(QueryBuilders.matchQuery("title",search), ScoreFunctionBuilders.weightFactorFunction(4)));
//        boolQuery.should(QueryBuilders.functionScoreQuery(QueryBuilders.matchQuery("tag",search), ScoreFunctionBuilders.weightFactorFunction(3)));
//        boolQuery.should(QueryBuilders.functionScoreQuery(QueryBuilders.matchQuery("channelName",search), ScoreFunctionBuilders.weightFactorFunction(2)));
//        boolQuery.should(QueryBuilders.functionScoreQuery(QueryBuilders.matchQuery("content",search), ScoreFunctionBuilders.weightFactorFunction(1)));
//        searchSourceBuilder.query(boolQuery);
//      //  searchSourceBuilder.sort(SortBuilders.fieldSort("viewnum").order(SortOrder.DESC));
//        //searchSourceBuilder.sort(SortBuilders.fieldSort("createDate").order(SortOrder.DESC));

        searchSourceBuilder.from((1 - 1) * 10); // 起始位置
        searchSourceBuilder.size(10); // 分页大小

        //自定义高亮 查找
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("*",20,20);
        highlightBuilder.requireFieldMatch(false);//如果要多个字段高亮,这项要为false
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");

        searchSourceBuilder.highlighter(highlightBuilder);

        //3.将 SearchSourceBuilder 添加到 SearchRequest中
        searchRequest.source(searchSourceBuilder);

        //4.执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        //5.解析查询结果
        System.out.println("花费的时长：" + searchResponse.getTook());

        SearchHits hits = searchResponse.getHits();
        System.out.println("符合条件的总文档数量：" + hits.getTotalHits().value);


        List<Map<String,Object>> maps = new ArrayList<>();
        hits.forEach(p -> {
            System.out.println("文档原生信息：" + p.getSourceAsString());
            System.out.println("高亮信息：" + p.getHighlightFields());
            Map<String, Object> map=p.getSourceAsMap();
            Map<String, HighlightField> m=p.getHighlightFields();

            StringBuilder stringBuilder=new StringBuilder();
            for (HighlightField h:m.values()){
                Text[] texts=h.getFragments();
                for (int i = 0; i <texts.length ; i++) {
                    Text text=texts[i];
                    stringBuilder.append(text.string());
                }
                if (stringBuilder.length() > 50) {
                    // 使用substring方法对StringBuilder进行截取
                    stringBuilder.setLength(50);
                }
            }
            String s= map.get("content")==null ? "": (String)map.get("content");
            StringBuilder c=new StringBuilder(s);

            if (c.length() > 50) {
                // 使用substring方法对StringBuilder进行截取
                c.setLength(50);
            }
            map.put("content",c.toString());
            map.put("hights",stringBuilder.toString());
            maps.add(map);
        });
        Map<String,Object> map=new HashMap<>();
        map.put("data",maps);
        map.put("total",hits.getTotalHits().value);
        map.put("keyword",search);
        return map;


    }


    /**
     * 判断创建的索引是否存在
     * @param indexName 索引名称
     * @return 是否存在
     * @throws Exception
     */
    public boolean existIndexName(String indexName,String idValue) throws Exception{
        GetRequest request = new GetRequest(indexName, idValue);
        //不获取返回的_source 的上下文
        request.fetchSourceContext(new FetchSourceContext(false));
        request.storedFields("_none");
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        return  exists;
    }


    /**
     * 通过id更新文档数据
     * @param t
     * @param indexName
     * @param <T>
     * @throws Exception
     */
    public <T> void updateDocumentById(T t,String indexName) throws Exception{
        Object val= ReflectUtils.getObjectByFeild(t,ID);
        if(val==null){
            return;
        }
        String id=String.valueOf(val);
        UpdateRequest request = new UpdateRequest(indexName, id);
        request.timeout("1s");
        request.doc(JSON.toJSONString(t),XContentType.JSON);
        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }


    /**
     * 添加单个索引数据
     * @param t 对象
     * @param indexName 索引名称
     * @param <T> 数据泛型
     * @throws Exception
     */
    public <T> void addDocument(T t,String indexName) throws Exception{
        Object val= ReflectUtils.getObjectByFeild(t,ID);
        if(val==null){
            throw new Exception("id不得为空");
        }
        String id=String.valueOf(val);
        //创建请求
        IndexRequest request = new IndexRequest(indexName);
        //规则
        request.id(id).timeout(TimeValue.timeValueSeconds(1));
        //将数据放到请求中
        request.source(JSON.toJSONString(t), XContentType.JSON);
        //客户端发送请求，获取相应的结果
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        //打印一下
        System.out.println(response.toString());
        System.out.println(response.status());
    }


    public void addDocument(String indexName,Map<String,Object> map) throws Exception{
        String id=UUID.randomUUID().toString();
        //创建请求
        IndexRequest request = new IndexRequest(indexName);
        //规则
        request.id(id).timeout(TimeValue.timeValueSeconds(1));
        //将数据放到请求中
        request.source(JSON.toJSONString(map), XContentType.JSON);
        //客户端发送请求，获取相应的结果
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        //打印一下
        System.out.println(response.toString());
        System.out.println(response.status());
    }


    public List<Map<String,Object>> searchFuzzines(String indexName,String field,String searchStr) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(field, searchStr)
                .fuzziness(Fuzziness.AUTO);

        searchSourceBuilder.query(matchQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        List<Map<String,Object>> maps = new ArrayList<Map<String, Object>>();
        for (SearchHit hit : hits) {
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("id",hit.getId());
            map.put("indexName",hit.getIndex());
            map.put("data",hit.getSourceAsMap());
            maps.add(map);
        }
        return maps;
    }



    /**
     * 删除索引
     * @param indexName
     * @throws IOException
     */
    public void deleteIndex(String indexName) throws IOException{
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println("是否删除"+response);
    }





    @Autowired
    private JestHttpClient esClient;


    //searchContent是要查询的内容
    public void searchProduct(String searchContent) throws IOException {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //添加查询条件,QueryBuilders组合查询，这里我们可以和上面再kibana中查询语句对比一下
        searchSourceBuilder.query(QueryBuilders.boolQuery()
                //匹配查询条件
                .must(QueryBuilders.matchQuery("spu_name",searchContent))
                .must(QueryBuilders.matchQuery("status",1)))
                //分页查询，从第0条，查询20条数据
                .from(0).size(20);

        //建立查询
        Search search = new Search.Builder(searchSourceBuilder.toString())
                //这里我们查询shop-trade索引（相当于数据库）
                .addIndex("shop-trade")
                .build();

        //执行查询返回结果
        SearchResult searchResult = esClient.execute(search);
        //将数据转成json格式
        String jsonString = searchResult.getJsonString();

        System.out.println(jsonString);
    }


    /**
     * 批量添加list 数据
     * @param tList  数据集合
     * @param <T>  数据泛型
     */
    public  <T> void addList(List<T> tList, String indexName){
        try {
            BulkRequest request = new BulkRequest();
            request.timeout("10s");
            //进行批处理请求
            for (int i = 0; i <tList.size() ; i++) {
                T t=tList.get(i);
                Object val=ReflectUtils.getObjectByFeild(t,ID);
                if(val==null){
                    continue;
                }
                String id=String.valueOf(val);
                request.add(
                        new IndexRequest(indexName)
                                .id(id)
                                .source(JSON.toJSONString(t),XContentType.JSON));
                System.out.println("添加id==>"+id);
            }
            BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
            System.out.println(response.hasFailures());
        }catch (IOException e){
            e.printStackTrace();
        }
    }


    /**
     * 根据id删除索引对应的id数据
     * @param indexName 索引名
     * @param idValue  要删除的id值
     * @throws IOException
     */
    public void deleteById(String indexName,String idValue) throws IOException{
        DeleteRequest request = new DeleteRequest(indexName, idValue);
        request.timeout("1s");
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }


    /**
     * 根据搜索数据
     * @param indexName 索引名称
     * @param field 字段属性
     * @param keyword 关键字
     * @param cls  反射
     * @param <T> 泛型
     * @return
     * @throws Exception
     */
    public <T> List<T>  searchList(String indexName,String field,String keyword,Class<T> cls) throws Exception{
        SearchRequest request = new SearchRequest(indexName);
        //构建搜索条件
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //查询条件使用QueryBuilders工具来实现
        //QueryBuilders.termQuery 精准查询
        //QueryBuilders.matchAllQuery() 匹配全部
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery(field, keyword);
        builder.query(matchQuery);
        builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] searchHits=response.getHits().getHits();
        List<T> tList=new ArrayList<>();
        for (int i = 0; i < searchHits.length; i++) {
            SearchHit hits=searchHits[i];
            Map<String, Object> map=hits.getSourceAsMap();
            T t= MapUtils.getObject(map,cls);
            tList.add(t);
        }
        return tList;
    }

    /**
     * 搜索构建器
     * @param indexName 索引名称
     * @param builder  构建器
     * @param cls  反射类
     * @param <T>  反射泛型
     * @return  数据对象
     * @throws Exception
     */
    public <T> Map<String, Object> searchListObject(String indexName,SearchSourceBuilder builder,Class<T> cls) throws Exception{

        SearchRequest request = new SearchRequest(indexName);
        builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);


        SearchHit[] searchHits=response.getHits().getHits();
        Long toatl=response.getHits().getTotalHits().value;
        List<T> tList=new ArrayList<>();
        for (int i = 0; i < searchHits.length; i++) {
            SearchHit hits=searchHits[i];
            Map<String, Object> map=hits.getSourceAsMap();
            T t= MapUtils.getObject(map,cls);
            tList.add(t);
        }
        Map<String, Object> map=new HashMap<>();
        map.put("data",tList);
        map.put("total",toatl);
        return map;
    }

}
